package name.fowler.refactoring.simplestore;

import java.util.ArrayList;
import java.util.List;

public class Customer {
	private String name;
	private List<Rental> movieRenatals = new ArrayList<Rental>();
	private FrequentPointCalculator frequentPointCalculator;

	public Customer(String name, FrequentPointCalculator frequentPointCalculator) {
		this.frequentPointCalculator = frequentPointCalculator;
		this.name = name;
	}
	public Customer(String name) {
		this(name, new DefaultFrequentPointCalculator());
	}
	
	public List<Rental> getMovieRenatals() {
		return movieRenatals;
	}

	public String getName() {
		return name;
	}

	public void addRental(Rental arg) {
		movieRenatals.add(arg);
	}

	/**
	 * Get the report with the total amount and frequent points for each rental
	 * 
	 * @return the final report
	 */
	public String getStatement() {
		String result = "Rental record for " + name + "\n";
		double totalAmount = 0;

		for (Rental each : movieRenatals) {
			result += showFigureForCurrentRental(each, getAmount(each));
			totalAmount += getAmount(each);
		}
		result = addFooterLines(totalAmount, frequentPointCalculator.getFrequentPoints(this));
		return result;
	}

	private String showFigureForCurrentRental(Rental each, double thisAmount) {
		return "\t" + each.getMovie().getTitle() + "\t" + thisAmount + "\n";
	}

	private String addFooterLines(double totalAmount, int frequentRenterPoints) {
		String footer = "Amount owed is " + totalAmount + "\n";
		footer += "You earned " + frequentRenterPoints
				+ " frequent renter points.";
		return footer;
	}

	/**
	 * get amount by price code and rented days
	 * 
	 * @param rental
	 * @return
	 */
	private double getAmount(Rental rental) {
		double thisAmount = 0;
		int bonusDayCountRegular = 2;
		int bonusDayCountChildren = 3;
		switch (rental.getMovie().getPriceCode()) {
		case Regular:
			thisAmount = getRegularAmount(rental, thisAmount,
					bonusDayCountRegular);
			break;
		case NewRelease:
			thisAmount = getNewReleaseAmount(rental, thisAmount);
			break;
		case Childrens:
			thisAmount = getChildrenAmount(rental, thisAmount,
					bonusDayCountChildren);
			break;
		}
		return thisAmount;
	}

	private double getNewReleaseAmount(Rental rental, final double thisAmount) {
		return thisAmount + rental.getDaysRented() * 3;
	}

	private double getChildrenAmount(Rental rental, final double thisAmount,
			int bonusDayCountChildren) {
		double additionAmount = 1.5;
		if (rental.getDaysRented() > bonusDayCountChildren) {
			additionAmount = (rental.getDaysRented() - 3) * 1.5;
		}
		return thisAmount + additionAmount;
	}

	private double getRegularAmount(Rental rental, final double thisAmount,
			int bonusDayCountRegular) {
		double accAmount = thisAmount + 2;
		if (rental.getDaysRented() > bonusDayCountRegular) {
			accAmount += (rental.getDaysRented() - 2) * 1.5;
		}
		return accAmount;
	}
}
